/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2009-2020 Rock Mao
* creator : Rock Mao
* created : 2009-5-2   22:29
* filename: LaborCamera.h
-----------------------------------------------------------------------------
*/

#ifndef __LABORCAMERA_H__
#define __LABORCAMERA_H__
#include "../LaborCoreDef.h"
#include "LaborFrustum.h"


NAMESPACE_LABOR3D_BEGIN

class LABORCORE_API CLCamera  : public CLFrustum
{
protected:
	//zQuat		m_quatRot;
	CLPoint3		m_vPos;
	CLPoint3		m_vLookAt;

	/// fix on y up direction
	bool		m_bFixed;

	CLPoint3		m_vDirection, m_vRight, m_vUp;

	///// Whether to yaw around a fixed axis.
	//bool m_bYawFixed;
	///// Fixed axis to yaw around
	//CLPoint3 m_pointYawFixedAxis;

	float	m_fYawAngle;
	float	m_fPitchAngle;
	float	m_fRollAngle;
public:
	CLCamera();
	CLCamera(CLCamera *camera);
	~CLCamera();
public:
	/// init form eye point and a quadrangle
	void init( const CLPoint3& ptPos, const CLPoint3& ptStart, const CLPoint3& ptEnd );


	///< Rolls the camera anticlockwise, in degrees, around its local z axis.
	void roll( float fRadian );
	///< Rotates the camera anticlockwise around it's local y axis.
	void yaw( float fRadian );
	///< Pitches the camera up/down anticlockwise around it's local z axis.
	void pitch( float fRadian );

	///< Points the camera at a location in worldspace.
	void lookAt( const CLPoint3& pointLookAt );
	void lookAt( float x, float y, float z );

	///< Rotate the camera around an arbitrary axis.
	void rotate( const CLPoint3& pointAxis, float fRadian );
	void rotate( const CLQuat &quatRot );

	///< Sets the camera's direction.
	//void setDirection( float x, float y, float z );
	void setDirection( const CLPoint3& pointDirection, const CLPoint3& pointUp );

	///< Gets vector about camera.
	const CLPoint3 &getDirection() const;
	const CLPoint3 &getRight() const;
	const CLPoint3 &getUp() const;

	///< Sets the camera's position
	void setPosition(const CLPoint3 &pointPos);
	const CLPoint3 &getPosition();

	void onScreenChanged( int nScreenWidth, int nScreenHeight );

	///<
	void zoom( float fDist );

	///< Moves the camera along its direction
	void move( const CLPoint3 &point );
	///< Moves the camera's position by the vector offset provided along it's own axes (relative to orientation).
	void moveRelative( const CLPoint3 &point );

	void moveForward( float fDistance );
	void moveRight( float fDistance );
	void moveUp( float fDistance );

	CLRay getCameraRay( float screenX, float screenY );

	inline float getPitch(void)   { return m_fPitchAngle; }
	inline float getRoll(void)   { return m_fRollAngle; }
	inline float getYaw(void)   { return m_fYawAngle; }


	/// set / get fixed
	inline void setFixed( bool bFixed )
	{
		m_bFixed = bFixed;
	}
	inline bool getFixed()
	{
		return m_bFixed;
	}

	inline CLPoint3 getLookAt(){
		return m_vLookAt;
	}
	/////////////////////////////////
protected:
	//// Internal functions for calcs
	void _updateFrustum(void);
	virtual void _updateView(void);

	void _viewChanged();
	void _frustumChanged();
};

NAMESPACE_LABOR3D_END

#endif